using System;
using System.Collections.Generic;
using System.Text;

namespace OracleInternal.I18N
{
	[Serializable]
	internal class TLBConvZHTEUC : TLBConvLC
	{
		public override int MinBytesPerChar => 1;

		public override int MaxBytesPerChar => 4;

		public TLBConvZHTEUC()
		{
			m_groupId = 5;
		}

		private int GetCharsLengthZHTEUCImpl(byte[] bytes, int offset, int count, ref int bytesCounted)
		{
			int i = offset;
			int num = offset + count;
			if (num > bytes.Length)
			{
				num = bytes.Length;
			}
			int num2 = 0;
			int num4;
			for (; i < num; i += num4)
			{
				int num3 = bytes[i] & 0xFF;
				num4 = 1;
				int num5 = 0;
				bool flag = true;
				if (num3 > 127)
				{
					if (i + 1 >= num)
					{
						break;
					}
					num3 = (num3 << 8) | (bytes[i + 1] & 0xFF);
					num4 = 2;
					for (int j = 0; j < m_ucsCharLeadingCode.Length; j++)
					{
						if (num3 == m_ucsCharLeadingCode[j][0])
						{
							if (i + 3 >= num)
							{
								flag = false;
								break;
							}
							num5 = m_ucsCharLeadingCode[j][1];
							num3 = (num3 << 16) | ((bytes[i + 2] << 8) & 0xFF00) | (bytes[i + 3] & 0xFF);
							num4 = 4;
							break;
						}
					}
				}
				if (!flag)
				{
					break;
				}
				int num6 = ((num3 >> 8) & 0xFF) + num5;
				int num7 = num3 & 0xFF;
				int num8 = ((m_ucsCharLevel1[num6] == '\uffff' || m_ucsCharLevel2[m_ucsCharLevel1[num6] + num7] == 65535) ? m_ucsCharReplacement : m_ucsCharLevel2[m_ucsCharLevel1[num6] + num7]);
				num2 = (((num8 & 0xFFFFFFFFu) <= 65535) ? (num2 + 1) : (num2 + 2));
			}
			bytesCounted = i - offset;
			return num2;
		}

		private int GetBytesOffsetZHTEUCImpl(byte[] bytes, int offset, int count, ref int charCount)
		{
			int i = offset;
			int num = offset + count;
			if (num > bytes.Length)
			{
				num = bytes.Length;
			}
			int num2 = 0;
			int num4;
			for (; i < num; i += num4)
			{
				if (num2 >= charCount)
				{
					break;
				}
				int num3 = bytes[i] & 0xFF;
				num4 = 1;
				int num5 = 0;
				bool flag = true;
				if (num3 > 127)
				{
					if (i + 1 >= num)
					{
						break;
					}
					num3 = (num3 << 8) | (bytes[i + 1] & 0xFF);
					num4 = 2;
					for (int j = 0; j < m_ucsCharLeadingCode.Length; j++)
					{
						if (num3 == m_ucsCharLeadingCode[j][0])
						{
							if (i + 3 >= num)
							{
								flag = false;
								break;
							}
							num5 = m_ucsCharLeadingCode[j][1];
							num3 = (num3 << 16) | ((bytes[i + 2] << 8) & 0xFF00) | (bytes[i + 3] & 0xFF);
							num4 = 4;
							break;
						}
					}
				}
				if (!flag)
				{
					break;
				}
				int num6 = ((num3 >> 8) & 0xFF) + num5;
				int num7 = num3 & 0xFF;
				int num8 = ((m_ucsCharLevel1[num6] == '\uffff' || m_ucsCharLevel2[m_ucsCharLevel1[num6] + num7] == 65535) ? m_ucsCharReplacement : m_ucsCharLevel2[m_ucsCharLevel1[num6] + num7]);
				num2 = (((num8 & 0xFFFFFFFFu) <= 65535) ? (num2 + 1) : (num2 + 2));
			}
			charCount = num2;
			return i - offset;
		}

		public override int GetBytesOffset(byte[] bytes, int byteOffset, int byteCount, int charCount)
		{
			int charCount2 = charCount;
			return GetBytesOffsetZHTEUCImpl(bytes, byteOffset, byteCount, ref charCount2);
		}

		private int GetRemainingBytes(int oraChar)
		{
			int result = 2;
			for (int i = 0; i < m_ucsCharLeadingCode.Length; i++)
			{
				if (oraChar == m_ucsCharLeadingCode[i][0])
				{
					result = 4;
					break;
				}
			}
			return result;
		}

		public override int GetCharsLength(byte[] bytes, int byteOffset, int byteCount)
		{
			int bytesCounted = 0;
			return GetCharsLengthZHTEUCImpl(bytes, byteOffset, byteCount, ref bytesCounted);
		}

		public override int GetCharsLength(ArraySegment<byte> bytes, int bytesOffset, int bytesCount)
		{
			int bytesCounted = 0;
			return GetCharsLengthZHTEUCImpl(bytes.Array, bytes.Offset + bytesOffset, bytesCount, ref bytesCounted);
		}

		public override int GetCharsLength(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount)
		{
			int num = 0;
			int bytesCounted = 0;
			int num2 = 0;
			int continuationOffset = 0;
			byte[] array = null;
			int num3 = 0;
			int idx = 0;
			int offSet = bytes[0].Offset;
			bool flag = false;
			if (bytesOffset > 0)
			{
				UTF16ConvUtility.GetSegementIndices(bytes, bytesOffset, ref idx, ref offSet);
			}
			for (int i = idx; i < bytes.Count; i++)
			{
				if (flag)
				{
					break;
				}
				int num4 = bytes[i].Offset + continuationOffset;
				int num5 = bytes[i].Count - continuationOffset;
				if (i == idx)
				{
					num4 = offSet + continuationOffset;
					num5 = bytes[i].Count - (offSet - bytes[i].Offset) - continuationOffset;
				}
				if (bytesCount - num2 <= num5)
				{
					num5 = bytesCount - num2;
					flag = true;
				}
				int charsLengthZHTEUCImpl = GetCharsLengthZHTEUCImpl(bytes[i].Array, num4, num5, ref bytesCounted);
				num += charsLengthZHTEUCImpl;
				num2 += bytesCounted;
				if (bytesCounted < num5 && !flag && i < bytes.Count - 1)
				{
					if (array == null)
					{
						array = new byte[4];
					}
					byte[] array2 = bytes[i + 1].Array;
					int num6 = num4 + bytesCounted;
					int num7 = bytes[i].Array[num6] & 0xFF;
					byte b = 0;
					b = ((bytesCounted != num5 - 1) ? bytes[i].Array[num6 + 1] : array2[bytes[i + 1].Offset]);
					num7 = (num7 << 8) | (b & 0xFF);
					int remainingBytes = GetRemainingBytes(num7);
					int buffer1Bytes = num5 - bytesCounted;
					if (remainingBytes == 4)
					{
						UTF16ConvUtility.GetRemainingBytes(4, bytes[i].Array, num6, buffer1Bytes, bytes, ref i, ref continuationOffset, array);
						num3 = 4;
					}
					else
					{
						UTF16ConvUtility.GetRemainingBytes(2, bytes[i].Array, num6, buffer1Bytes, bytes, ref i, ref continuationOffset, array);
						num3 = 2;
					}
					charsLengthZHTEUCImpl = GetCharsLengthZHTEUCImpl(array, 0, num3, ref bytesCounted);
					num += charsLengthZHTEUCImpl;
					num2 += bytesCounted;
				}
				else
				{
					continuationOffset = 0;
				}
			}
			return num;
		}

		public override int ConvertBytesToChars(byte[] bytes, int offset, int count, char[] chars, int charOffset, ref int charCount, bool ccb)
		{
			int i = offset;
			if (i < 0)
			{
				i = 0;
			}
			int num = i + count;
			if (num > bytes.Length)
			{
				num = bytes.Length;
			}
			int num2 = charOffset;
			if (num2 < 0)
			{
				num2 = 0;
			}
			int num3 = num2 + charCount;
			if (num3 > chars.Length)
			{
				num3 = chars.Length;
			}
			int num5;
			for (; i < num; i += num5)
			{
				if (num2 >= num3)
				{
					break;
				}
				int num4 = bytes[i] & 0xFF;
				num5 = 1;
				int num6 = 0;
				bool flag = true;
				if (num4 > 127)
				{
					if (i + 1 >= num)
					{
						if (ccb)
						{
							break;
						}
						throw new DecoderFallbackException("Failed to convert bytes to Unicode");
					}
					num4 = (num4 << 8) | (bytes[i + 1] & 0xFF);
					num5 = 2;
					for (int j = 0; j < m_ucsCharLeadingCode.Length; j++)
					{
						if (num4 == m_ucsCharLeadingCode[j][0])
						{
							if (i + 3 >= num)
							{
								if (!ccb)
								{
									throw new DecoderFallbackException("Failed to convert bytes to Unicode");
								}
								flag = false;
								break;
							}
							num6 = m_ucsCharLeadingCode[j][1];
							num4 = (num4 << 16) | ((bytes[i + 2] << 8) & 0xFF00) | (bytes[i + 3] & 0xFF);
							num5 = 4;
							break;
						}
					}
				}
				if (!flag)
				{
					break;
				}
				int num7 = ((num4 >> 8) & 0xFF) + num6;
				int num8 = num4 & 0xFF;
				int num9;
				if (m_ucsCharLevel1[num7] != '\uffff' && m_ucsCharLevel2[m_ucsCharLevel1[num7] + num8] != 65535)
				{
					num9 = m_ucsCharLevel2[m_ucsCharLevel1[num7] + num8];
				}
				else
				{
					if (!ccb)
					{
						throw new DecoderFallbackException("Failed to convert bytes to Unicode");
					}
					num9 = m_ucsCharReplacement;
				}
				if ((num9 & 0xFFFFFFFFu) > 65535)
				{
					if (num2 >= num3)
					{
						break;
					}
					chars[num2++] = (char)(num9 >> 16);
					chars[num2++] = (char)((uint)num9 & 0xFFFFu);
				}
				else
				{
					chars[num2++] = (char)num9;
				}
			}
			charCount = num2 - charOffset;
			return i - offset;
		}

		public override int ConvertBytesToUTF16(byte[] bytes, int offset, int count, byte[] utfbytes, int utfOffset, ref int utfCount, bool ccb)
		{
			int i = offset;
			if (i < 0)
			{
				i = 0;
			}
			int num = i + count;
			if (num > bytes.Length)
			{
				num = bytes.Length;
			}
			int num2 = utfOffset;
			if (num2 < 0)
			{
				num2 = 0;
			}
			int num3 = num2 + utfCount;
			if (num3 > utfbytes.Length)
			{
				num3 = utfbytes.Length;
			}
			int num5;
			for (; i < num; i += num5)
			{
				if (num2 + 1 >= num3)
				{
					break;
				}
				int num4 = bytes[i] & 0xFF;
				num5 = 1;
				int num6 = 0;
				bool flag = true;
				if (num4 > 127)
				{
					if (i + 1 >= num)
					{
						if (ccb)
						{
							break;
						}
						throw new DecoderFallbackException("Failed to convert bytes to Unicode");
					}
					num4 = (num4 << 8) | (bytes[i + 1] & 0xFF);
					num5 = 2;
					for (int j = 0; j < m_ucsCharLeadingCode.Length; j++)
					{
						if (num4 == m_ucsCharLeadingCode[j][0])
						{
							if (i + 3 >= num)
							{
								if (!ccb)
								{
									throw new DecoderFallbackException("Failed to convert bytes to Unicode");
								}
								flag = false;
								break;
							}
							num6 = m_ucsCharLeadingCode[j][1];
							num4 = (num4 << 16) | ((bytes[i + 2] << 8) & 0xFF00) | (bytes[i + 3] & 0xFF);
							num5 = 4;
							break;
						}
					}
				}
				if (!flag)
				{
					break;
				}
				int num7 = ((num4 >> 8) & 0xFF) + num6;
				int num8 = num4 & 0xFF;
				int num9;
				if (m_ucsCharLevel1[num7] != '\uffff' && m_ucsCharLevel2[m_ucsCharLevel1[num7] + num8] != 65535)
				{
					num9 = m_ucsCharLevel2[m_ucsCharLevel1[num7] + num8];
				}
				else
				{
					if (!ccb)
					{
						throw new DecoderFallbackException("Failed to convert bytes to Unicode");
					}
					num9 = m_ucsCharReplacement;
				}
				if ((num9 & 0xFFFFFFFFu) > 65535)
				{
					if (num2 + 3 >= num3)
					{
						break;
					}
					char[] array = new char[2]
					{
						(char)(num9 >> 16),
						(char)((uint)num9 & 0xFFFFu)
					};
					utfbytes[num2++] = (byte)(array[0] & 0xFFu);
					utfbytes[num2++] = (byte)((int)array[0] >> 8);
					utfbytes[num2++] = (byte)(array[1] & 0xFFu);
					utfbytes[num2++] = (byte)((int)array[1] >> 8);
				}
				else
				{
					utfbytes[num2++] = (byte)((uint)num9 & 0xFFu);
					utfbytes[num2++] = (byte)(num9 >> 8);
				}
			}
			utfCount = num2 - utfOffset;
			return i - offset;
		}

		private int ConvertByteArraySegListToCharsImpl<T>(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount, T[] chars, int charOffset, ref int charCount, bool bUseReplacementChar, ConvertByteToCharsDelegate<T> t)
		{
			int num = charOffset;
			int charCount2 = charCount;
			int num2 = 0;
			int num3 = 0;
			int continuationOffset = 0;
			byte[] array = null;
			int num4 = 0;
			int idx = 0;
			int offSet = bytes[0].Offset;
			bool flag = false;
			if (bytesOffset > 0)
			{
				UTF16ConvUtility.GetSegementIndices(bytes, bytesOffset, ref idx, ref offSet);
			}
			for (int i = idx; i < bytes.Count; i++)
			{
				if (flag)
				{
					break;
				}
				if (charCount2 <= 0)
				{
					break;
				}
				int num5 = bytes[i].Offset + continuationOffset;
				int num6 = bytes[i].Count - continuationOffset;
				if (i == idx)
				{
					num5 = offSet + continuationOffset;
					num6 = bytes[i].Count - (offSet - bytes[i].Offset) - continuationOffset;
				}
				if (bytesCount - num3 <= num6)
				{
					num6 = bytesCount - num3;
					flag = true;
				}
				int num7 = t(bytes[i].Array, num5, num6, chars, num, ref charCount2, bUseReplacementChar);
				num3 += num7;
				num += charCount2;
				num2 += charCount2;
				charCount2 = charCount - num2;
				if (charCount2 > 0 && num7 < num6 && !flag && i < bytes.Count - 1)
				{
					if (array == null)
					{
						array = new byte[4];
					}
					byte[] array2 = bytes[i + 1].Array;
					int num8 = num5 + num7;
					int num9 = bytes[i].Array[num8] & 0xFF;
					byte b = 0;
					b = ((num7 != num6 - 1) ? bytes[i].Array[num8 + 1] : array2[bytes[i + 1].Offset]);
					num9 = (num9 << 8) | (b & 0xFF);
					int remainingBytes = GetRemainingBytes(num9);
					int buffer1Bytes = num6 - num7;
					if (remainingBytes == 4)
					{
						UTF16ConvUtility.GetRemainingBytes(4, bytes[i].Array, num8, buffer1Bytes, bytes, ref i, ref continuationOffset, array);
						num4 = 4;
					}
					else
					{
						UTF16ConvUtility.GetRemainingBytes(2, bytes[i].Array, num8, buffer1Bytes, bytes, ref i, ref continuationOffset, array);
						num4 = 2;
					}
					num7 = t(array, 0, num4, chars, num, ref charCount2, bUseReplacementChar);
					if (num7 == 0)
					{
						break;
					}
					num3 += num7;
					num += charCount2;
					num2 += charCount2;
					charCount2 = charCount - num2;
				}
				else
				{
					continuationOffset = 0;
				}
			}
			charCount = num2;
			return num3;
		}

		public override int GetBytesOffset(IList<ArraySegment<byte>> bytes, int charCount)
		{
			int charCount2 = charCount;
			int num = 0;
			int num2 = 0;
			int continuationOffset = 0;
			byte[] array = null;
			int num3 = 0;
			for (int i = 0; i < bytes.Count; i++)
			{
				if (num >= charCount)
				{
					break;
				}
				int num4 = bytes[i].Offset + continuationOffset;
				int num5 = bytes[i].Count - continuationOffset;
				byte[] array2 = bytes[i].Array;
				int bytesOffsetZHTEUCImpl = GetBytesOffsetZHTEUCImpl(array2, num4, num5, ref charCount2);
				num2 += bytesOffsetZHTEUCImpl;
				num += charCount2;
				charCount2 = charCount - num;
				if (charCount2 > 0 && bytesOffsetZHTEUCImpl < num5 && i < bytes.Count - 1)
				{
					if (array == null)
					{
						array = new byte[4];
					}
					byte[] array3 = bytes[i + 1].Array;
					int num6 = num4 + bytesOffsetZHTEUCImpl;
					int num7 = array2[num6] & 0xFF;
					byte b = 0;
					b = ((bytesOffsetZHTEUCImpl != num5 - 1) ? array2[num6 + 1] : array3[bytes[i + 1].Offset]);
					num7 = (num7 << 8) | (b & 0xFF);
					int remainingBytes = GetRemainingBytes(num7);
					int buffer1Bytes = num5 - bytesOffsetZHTEUCImpl;
					if (remainingBytes == 4)
					{
						UTF16ConvUtility.GetRemainingBytes(4, array2, num6, buffer1Bytes, bytes, ref i, ref continuationOffset, array);
						num3 = 4;
					}
					else
					{
						UTF16ConvUtility.GetRemainingBytes(2, array2, num6, buffer1Bytes, bytes, ref i, ref continuationOffset, array);
						num3 = 2;
					}
					bytesOffsetZHTEUCImpl = GetBytesOffsetZHTEUCImpl(array, 0, num3, ref charCount2);
					num2 += bytesOffsetZHTEUCImpl;
					num += charCount2;
					charCount2 = charCount - num;
				}
				else
				{
					continuationOffset = 0;
				}
			}
			return num2;
		}

		public override int ConvertBytesToChars(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount, char[] chars, int charOffset, ref int charCount, bool bUseReplacementChar)
		{
			if (bytes.Count == 1)
			{
				return ConvertBytesToChars(bytes[0].Array, bytes[0].Offset + bytesOffset, bytesCount, chars, charOffset, ref charCount, bUseReplacementChar);
			}
			return ConvertByteArraySegListToCharsImpl(bytes, bytesOffset, bytesCount, chars, charOffset, ref charCount, bUseReplacementChar, ConvertBytesToChars);
		}
	}
}
